{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Hello Feature Class example: using the feature classes to calculate features"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This example shows how to use the Radiomics package to directly instantiate the feature classes for feature extraction. \n",
    "Note that this is not the intended standard use. For an example on the standard use with feature extractor, see the `helloRadiomics` example."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from __future__ import annotations\n",
    "\n",
    "import SimpleITK as sitk\n",
    "\n",
    "import radiomics\n",
    "from radiomics import firstorder, glcm, glrlm, glszm, imageoperations, shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Getting the test case"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Test cases can be downloaded to temporary files. This is handled by the `radiomics.getTestCase()` function, which checks if the requested test case is available and if not, downloads it. It returns a tuple with the location of the image and mask of the requested test case, or (None, None) if it fails.\n",
    "\n",
    "Alternatively, if the data is available somewhere locally, this directory can be passed as a second argument to `radiomics.getTestCase()`. If that directory does not exist or does not contain the testcase, functionality reverts to default and tries to download the test data.\n",
    "\n",
    "If getting the test case fails, PyRadiomics will log an error explaining the cause."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "imageName, maskName = radiomics.getTestCase('brain1')\n",
    "\n",
    "if imageName is None or maskName is None:  # Something went wrong, in this case PyRadiomics will also log an error\n",
    "    msg = 'Error getting testcase!'\n",
    "    raise Exception(msg)  # Raise exception to prevent cells below from running in case of \"run all\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "image = sitk.ReadImage(imageName)\n",
    "mask = sitk.ReadImage(maskName)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Preprocess the image"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Extraction Settings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "settings = {}\n",
    "settings['binWidth'] = 25\n",
    "settings['resampledPixelSpacing'] = None\n",
    "# settings['resampledPixelSpacing'] = [3, 3, 3]  # This is an example for defining resampling (voxels with size 3x3x3mm)\n",
    "settings['interpolator'] = 'sitkBSpline'\n",
    "settings['verbose'] = True"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### If enabled, resample the image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Resample if necessary\n",
    "interpolator = settings.get('interpolator')\n",
    "resampledPixelSpacing = settings.get('resampledPixelSpacing')\n",
    "if interpolator is not None and resampledPixelSpacing is not None:\n",
    "  image, mask = imageoperations.resampleImage(image, mask, **settings)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## Calculate features using original image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Crop the image\n",
    "# bb is the bounding box, upon which the image and mask are cropped\n",
    "bb, correctedMask = imageoperations.checkMask(image, mask, label=1)\n",
    "if correctedMask is not None:\n",
    "    mask = correctedMask\n",
    "croppedImage, croppedMask = imageoperations.cropToTumorMask(image, mask, bb)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Calculate Firstorder features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "firstOrderFeatures = firstorder.RadiomicsFirstOrder(croppedImage, croppedMask, **settings)\n",
    "\n",
    "# Set the features to be calculated\n",
    "firstOrderFeatures.enableFeatureByName('Mean', True)\n",
    "# firstOrderFeatures.enableAllFeatures()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Will calculate the following first order features: \n",
      "Mean\n",
      "\n",
      "    **8. Mean**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{mean} = \\frac{1}{N_p}\\displaystyle\\sum^{N_p}_{i=1}{\\textbf{X}(i)}\n",
      "\n",
      "    The average gray level intensity within the ROI.\n",
      "    \n"
     ]
    }
   ],
   "source": [
    "# Print out the docstrings of the enabled features\n",
    "print('Will calculate the following first order features: ')\n",
    "for f in firstOrderFeatures.enabledFeatures:\n",
    "  print(f)\n",
    "  print(getattr(firstOrderFeatures, f'get{f}FeatureValue').__doc__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Calculating first order features...\n",
      "done\n",
      "Calculated first order features: \n",
      "   Mean : 825.2354363065023\n"
     ]
    }
   ],
   "source": [
    "# Calculate the features and print(out result)\n",
    "print('Calculating first order features...',)\n",
    "result = firstOrderFeatures.execute()\n",
    "print('done')\n",
    "\n",
    "print('Calculated first order features: ')\n",
    "for (key, val) in result.items():\n",
    "  print('  ', key, ':', val)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Calculate Shape Features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "shapeFeatures = shape.RadiomicsShape(croppedImage, croppedMask, **settings)\n",
    "\n",
    "# Set the features to be calculated\n",
    "# shapeFeatures.enableFeatureByName('Volume', True)\n",
    "shapeFeatures.enableAllFeatures()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Will calculate the following shape features: \n",
      "Maximum2DDiameterRow\n",
      "\n",
      "    **12. Maximum 2D diameter (Row)**\n",
      "\n",
      "    Maximum 2D diameter (Row) is defined as the largest pairwise Euclidean distance between tumor surface mesh\n",
      "    vertices in the column-slice (usually the sagittal) plane.\n",
      "    \n",
      "VoxelVolume\n",
      "\n",
      "    **2. Voxel Volume**\n",
      "\n",
      "    .. math::\n",
      "      V_{voxel} = \\displaystyle\\sum^{N_v}_{k=1}{V_k}\n",
      "\n",
      "    The volume of the ROI :math:`V_{voxel}` is approximated by multiplying the number of voxels in the ROI by the volume\n",
      "    of a single voxel :math:`V_k`. This is a less precise approximation of the volume and is not used in subsequent\n",
      "    features. This feature does not make use of the mesh and is not used in calculation of other shape features.\n",
      "\n",
      "    .. note::\n",
      "      Defined in IBSI as ``Approximate Volume``.\n",
      "    \n",
      "Maximum3DDiameter\n",
      "\n",
      "    **9. Maximum 3D diameter**\n",
      "\n",
      "    Maximum 3D diameter is defined as the largest pairwise Euclidean distance between tumor surface mesh\n",
      "    vertices.\n",
      "\n",
      "    Also known as Feret Diameter.\n",
      "    \n",
      "MajorAxisLength\n",
      "\n",
      "    **13. Major Axis Length**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{major axis} = 4 \\sqrt{\\lambda_{major}}\n",
      "\n",
      "    This feature yield the largest axis length of the ROI-enclosing ellipsoid and is calculated using the largest\n",
      "    principal component :math:`\\lambda_{major}`.\n",
      "\n",
      "    The principal component analysis is performed using the physical coordinates of the voxel centers defining the ROI.\n",
      "    It therefore takes spacing into account, but does not make use of the shape mesh.\n",
      "    \n",
      "Sphericity\n",
      "\n",
      "    **5. Sphericity**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{sphericity} = \\frac{\\sqrt[3]{36 \\pi V^2}}{A}\n",
      "\n",
      "    Sphericity is a measure of the roundness of the shape of the tumor region relative to a sphere. It is a\n",
      "    dimensionless measure, independent of scale and orientation. The value range is :math:`0 < sphericity \\leq 1`, where\n",
      "    a value of 1 indicates a perfect sphere (a sphere has the smallest possible surface area for a given volume,\n",
      "    compared to other solids).\n",
      "\n",
      "    .. note::\n",
      "      This feature is correlated to Compactness 1, Compactness 2 and Spherical Disproportion. In the default\n",
      "      parameter file provided in the ``pyradiomics/examples/exampleSettings`` folder, Compactness 1 and Compactness 2\n",
      "      are therefore disabled.\n",
      "    \n",
      "LeastAxisLength\n",
      "\n",
      "    **15. Least Axis Length**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{least axis} = 4 \\sqrt{\\lambda_{least}}\n",
      "\n",
      "    This feature yield the smallest axis length of the ROI-enclosing ellipsoid and is calculated using the largest\n",
      "    principal component :math:`\\lambda_{least}`. In case of a 2D segmentation, this value will be 0.\n",
      "\n",
      "    The principal component analysis is performed using the physical coordinates of the voxel centers defining the ROI.\n",
      "    It therefore takes spacing into account, but does not make use of the shape mesh.\n",
      "    \n",
      "Elongation\n",
      "\n",
      "    **16. Elongation**\n",
      "\n",
      "    Elongation shows the relationship between the two largest principal components in the ROI shape.\n",
      "    For computational reasons, this feature is defined as the inverse of true elongation.\n",
      "\n",
      "    .. math::\n",
      "      \\textit{elongation} = \\sqrt{\\frac{\\lambda_{minor}}{\\lambda_{major}}}\n",
      "\n",
      "    Here, :math:`\\lambda_{\\text{major}}` and :math:`\\lambda_{\\text{minor}}` are the lengths of the largest and second\n",
      "    largest principal component axes. The values range between 1 (where the cross section through the first and second\n",
      "    largest principal moments is circle-like (non-elongated)) and 0 (where the object is a maximally elongated: i.e. a 1\n",
      "    dimensional line).\n",
      "\n",
      "    The principal component analysis is performed using the physical coordinates of the voxel centers defining the ROI.\n",
      "    It therefore takes spacing into account, but does not make use of the shape mesh.\n",
      "    \n",
      "SurfaceVolumeRatio\n",
      "\n",
      "    **4. Surface Area to Volume ratio**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{surface to volume ratio} = \\frac{A}{V}\n",
      "\n",
      "    Here, a lower value indicates a more compact (sphere-like) shape. This feature is not dimensionless, and is\n",
      "    therefore (partly) dependent on the volume of the ROI.\n",
      "    \n",
      "Maximum2DDiameterSlice\n",
      "\n",
      "    **10. Maximum 2D diameter (Slice)**\n",
      "\n",
      "    Maximum 2D diameter (Slice) is defined as the largest pairwise Euclidean distance between tumor surface mesh\n",
      "    vertices in the row-column (generally the axial) plane.\n",
      "    \n",
      "Flatness\n",
      "\n",
      "    **17. Flatness**\n",
      "\n",
      "    Flatness shows the relationship between the largest and smallest principal components in the ROI shape.\n",
      "    For computational reasons, this feature is defined as the inverse of true flatness.\n",
      "\n",
      "    .. math::\n",
      "      \\textit{flatness} = \\sqrt{\\frac{\\lambda_{least}}{\\lambda_{major}}}\n",
      "\n",
      "    Here, :math:`\\lambda_{\\text{major}}` and :math:`\\lambda_{\\text{least}}` are the lengths of the largest and smallest\n",
      "    principal component axes. The values range between 1 (non-flat, sphere-like) and 0 (a flat object, or single-slice\n",
      "    segmentation).\n",
      "\n",
      "    The principal component analysis is performed using the physical coordinates of the voxel centers defining the ROI.\n",
      "    It therefore takes spacing into account, but does not make use of the shape mesh.\n",
      "    \n",
      "SurfaceArea\n",
      "\n",
      "    **3. Surface Area**\n",
      "\n",
      "    .. math::\n",
      "      A_i = \\frac{1}{2}|\\text{a}_i\\text{b}_i \\times \\text{a}_i\\text{c}_i| \\text{ (1)}\n",
      "\n",
      "      A = \\displaystyle\\sum^{N_f}_{i=1}{A_i} \\text{ (2)}\n",
      "\n",
      "    where:\n",
      "\n",
      "    :math:`\\text{a}_i\\text{b}_i` and :math:`\\text{a}_i\\text{c}_i` are edges of the :math:`i^{\\text{th}}` triangle in the\n",
      "    mesh, formed by vertices :math:`\\text{a}_i`, :math:`\\text{b}_i` and :math:`\\text{c}_i`.\n",
      "\n",
      "    To calculate the surface area, first the surface area :math:`A_i` of each triangle in the mesh is calculated (1).\n",
      "    The total surface area is then obtained by taking the sum of all calculated sub-areas (2).\n",
      "\n",
      "    .. note::\n",
      "      Defined in IBSI as ``Surface Area``.\n",
      "    \n",
      "MinorAxisLength\n",
      "\n",
      "    **14. Minor Axis Length**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{minor axis} = 4 \\sqrt{\\lambda_{minor}}\n",
      "\n",
      "    This feature yield the second-largest axis length of the ROI-enclosing ellipsoid and is calculated using the largest\n",
      "    principal component :math:`\\lambda_{minor}`.\n",
      "\n",
      "    The principal component analysis is performed using the physical coordinates of the voxel centers defining the ROI.\n",
      "    It therefore takes spacing into account, but does not make use of the shape mesh.\n",
      "    \n",
      "Maximum2DDiameterColumn\n",
      "\n",
      "    **11. Maximum 2D diameter (Column)**\n",
      "\n",
      "    Maximum 2D diameter (Column) is defined as the largest pairwise Euclidean distance between tumor surface mesh\n",
      "    vertices in the row-slice (usually the coronal) plane.\n",
      "    \n",
      "MeshVolume\n",
      "\n",
      "    **1. Mesh Volume**\n",
      "\n",
      "    .. math::\n",
      "      V_i = \\displaystyle\\frac{Oa_i \\cdot (Ob_i \\times Oc_i)}{6} \\text{ (1)}\n",
      "\n",
      "      V = \\displaystyle\\sum^{N_f}_{i=1}{V_i} \\text{ (2)}\n",
      "\n",
      "    The volume of the ROI :math:`V` is calculated from the triangle mesh of the ROI.\n",
      "    For each face :math:`i` in the mesh, defined by points :math:`a_i, b_i` and :math:`c_i`, the (signed) volume\n",
      "    :math:`V_f` of the tetrahedron defined by that face and the origin of the image (:math:`O`) is calculated. (1)\n",
      "    The sign of the volume is determined by the sign of the normal, which must be consistently defined as either facing\n",
      "    outward or inward of the ROI.\n",
      "\n",
      "    Then taking the sum of all :math:`V_i`, the total volume of the ROI is obtained (2)\n",
      "\n",
      "    .. note::\n",
      "      For more extensive documentation on how the volume is obtained using the surface mesh, see the IBSI document,\n",
      "      where this feature is defined as ``Volume``.\n",
      "    \n"
     ]
    }
   ],
   "source": [
    "# Print out the docstrings of the enabled features\n",
    "print('Will calculate the following shape features: ')\n",
    "for f in shapeFeatures.enabledFeatures:\n",
    "  print(f)\n",
    "  print(getattr(shapeFeatures, f'get{f}FeatureValue').__doc__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Calculating shape features...\n",
      "done\n",
      "Calculated shape features: \n",
      "   VoxelVolume : 16412.658691406243\n",
      "   Maximum3DDiameter : 69.60099030590368\n",
      "   MeshVolume : 16147.51180013021\n",
      "   MajorAxisLength : 61.99722046980879\n",
      "   Sphericity : 0.4798234536231475\n",
      "   LeastAxisLength : 28.584423185376522\n",
      "   Elongation : 0.5621171627174109\n",
      "   SurfaceVolumeRatio : 0.3987500788652454\n",
      "   Maximum2DDiameterSlice : 53.59397776919529\n",
      "   Flatness : 0.46105975346582634\n",
      "   SurfaceArea : 6438.821603779402\n",
      "   MinorAxisLength : 34.849701666854706\n",
      "   Maximum2DDiameterColumn : 49.490854979101925\n",
      "   Maximum2DDiameterRow : 65.88905951721043\n"
     ]
    }
   ],
   "source": [
    "# Calculate the features and print(out result)\n",
    "print('Calculating shape features...',)\n",
    "result = shapeFeatures.execute()\n",
    "print('done')\n",
    "\n",
    "print('Calculated shape features: ')\n",
    "for (key, val) in result.items():\n",
    "  print('  ', key, ':', val)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Calculate GLCM Features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "glcmFeatures = glcm.RadiomicsGLCM(croppedImage, croppedMask, **settings)\n",
    "\n",
    "# Set the features to be calculated\n",
    "# glcmFeatures.enableFeatureByName('SumEntropy', True)\n",
    "glcmFeatures.enableAllFeatures()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Will calculate the following GLCM features: \n",
      "JointAverage\n",
      "\n",
      "    **2. Joint Average**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{joint average} = \\mu_x = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_g}_{j=1}{p(i,j)i}\n",
      "\n",
      "    Returns the mean gray level intensity of the :math:`i` distribution.\n",
      "\n",
      "    .. warning::\n",
      "      As this formula represents the average of the distribution of :math:`i`, it is independent from the\n",
      "      distribution of :math:`j`. Therefore, only use this formula if the GLCM is symmetrical, where\n",
      "      :math:`p_x(i) = p_y(j) \\text{, where } i = j`.\n",
      "    \n",
      "SumAverage\n",
      "\n",
      "    **22. Sum Average**\n",
      "\n",
      "    .. math::\n",
      "\n",
      "      \\textit{sum average} = \\displaystyle\\sum^{2N_g}_{k=2}{p_{x+y}(k)k}\n",
      "\n",
      "    Sum Average measures the relationship between occurrences of pairs\n",
      "    with lower intensity values and occurrences of pairs with higher intensity\n",
      "    values.\n",
      "\n",
      "    .. warning::\n",
      "      When GLCM is symmetrical, :math:`\\mu_x = \\mu_y`, and therefore :math:`\\text{Sum Average} = \\mu_x + \\mu_y =\n",
      "      2 \\mu_x = 2 * Joint Average`. See formulas (4.), (5.) and (6.) defined\n",
      "      :ref:`here <radiomics-excluded-sumvariance-label>` for the proof that :math:`\\text{Sum Average} = \\mu_x + \\mu_y`.\n",
      "      In the default parameter files provided in the ``examples/exampleSettings``, this feature has been disabled.\n",
      "    \n",
      "JointEntropy\n",
      "\n",
      "    **12. Joint Entropy**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{joint entropy} = -\\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_g}_{j=1}\n",
      "      {p(i,j)\\log_2\\big(p(i,j)+\\epsilon\\big)}\n",
      "\n",
      "\n",
      "    Joint entropy is a measure of the randomness/variability in neighborhood intensity values.\n",
      "\n",
      "    .. note::\n",
      "      Defined by IBSI as Joint entropy\n",
      "    \n",
      "ClusterShade\n",
      "\n",
      "    **4. Cluster Shade**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{cluster shade} = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_g}_{j=1}\n",
      "      {\\big(i+j-\\mu_x-\\mu_y\\big)^3p(i,j)}\n",
      "\n",
      "    Cluster Shade is a measure of the skewness and uniformity of the GLCM.\n",
      "    A higher cluster shade implies greater asymmetry about the mean.\n",
      "    \n",
      "MaximumProbability\n",
      "\n",
      "    **21. Maximum Probability**\n",
      "\n",
      "    .. math::\n",
      "\n",
      "      \\textit{maximum probability} = \\max\\big(p(i,j)\\big)\n",
      "\n",
      "    Maximum Probability is occurrences of the most predominant pair of\n",
      "    neighboring intensity values.\n",
      "\n",
      "    .. note::\n",
      "      Defined by IBSI as Joint maximum\n",
      "    \n",
      "Idmn\n",
      "\n",
      "    **17. Inverse Difference Moment Normalized (IDMN)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{IDMN} = \\displaystyle\\sum^{N_g-1}_{k=0}{ \\frac{p_{x-y}(k)}{1+\\left(\\frac{k^2}{N_g^2}\\right)} }\n",
      "\n",
      "    IDMN (inverse difference moment normalized)  is a measure of the local\n",
      "    homogeneity of an image. IDMN weights are the inverse of the Contrast\n",
      "    weights (decreasing exponentially from the diagonal :math:`i=j` in the GLCM).\n",
      "    Unlike Homogeneity2, IDMN normalizes the square of the difference between\n",
      "    neighboring intensity values by dividing over the square of the total\n",
      "    number of discrete intensity values.\n",
      "    \n",
      "JointEnergy\n",
      "\n",
      "    **11. Joint Energy**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{joint energy} = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_g}_{j=1}{\\big(p(i,j)\\big)^2}\n",
      "\n",
      "    Energy is a measure of homogeneous patterns\n",
      "    in the image. A greater Energy implies that there are more instances\n",
      "    of intensity value pairs in the image that neighbor each other at\n",
      "    higher frequencies.\n",
      "\n",
      "    .. note::\n",
      "      Defined by IBSI as Angular Second Moment.\n",
      "    \n",
      "Contrast\n",
      "\n",
      "    **6. Contrast**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{contrast} = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_g}_{j=1}{(i-j)^2p(i,j)}\n",
      "\n",
      "    Contrast is a measure of the local intensity variation, favoring values away from the diagonal :math:`(i = j)`. A\n",
      "    larger value correlates with a greater disparity in intensity values among neighboring voxels.\n",
      "    \n",
      "DifferenceEntropy\n",
      "\n",
      "    **9. Difference Entropy**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{difference entropy} = \\displaystyle\\sum^{N_g-1}_{k=0}{p_{x-y}(k)\\log_2\\big(p_{x-y}(k)+\\epsilon\\big)}\n",
      "\n",
      "    Difference Entropy is a measure of the randomness/variability\n",
      "    in neighborhood intensity value differences.\n",
      "    \n",
      "InverseVariance\n",
      "\n",
      "    **20. Inverse Variance**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{inverse variance} = \\displaystyle\\sum^{N_g-1}_{k=1}{\\frac{p_{x-y}(k)}{k^2}}\n",
      "\n",
      "    Note that :math:`k=0` is skipped, as this would result in a division by 0.\n",
      "    \n",
      "DifferenceVariance\n",
      "\n",
      "    **10. Difference Variance**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{difference variance} = \\displaystyle\\sum^{N_g-1}_{k=0}{(k-DA)^2p_{x-y}(k)}\n",
      "\n",
      "    Difference Variance is a measure of heterogeneity that places higher weights on\n",
      "    differing intensity level pairs that deviate more from the mean.\n",
      "    \n",
      "Idn\n",
      "\n",
      "    **19. Inverse Difference Normalized (IDN)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{IDN} = \\displaystyle\\sum^{N_g-1}_{k=0}{ \\frac{p_{x-y}(k)}{1+\\left(\\frac{k}{N_g}\\right)} }\n",
      "\n",
      "    IDN (inverse difference normalized) is another measure of the local\n",
      "    homogeneity of an image. Unlike Homogeneity1, IDN normalizes the difference\n",
      "    between the neighboring intensity values by dividing over the total number\n",
      "    of discrete intensity values.\n",
      "    \n",
      "Idm\n",
      "\n",
      "    **15. Inverse Difference Moment (IDM)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{IDM} = \\displaystyle\\sum^{N_g-1}_{k=0}{\\frac{p_{x-y}(k)}{1+k^2}}\n",
      "\n",
      "    IDM (a.k.a Homogeneity 2) is a measure of the local\n",
      "    homogeneity of an image. IDM weights are the inverse of the Contrast\n",
      "    weights (decreasing exponentially from the diagonal i=j in the GLCM).\n",
      "    \n",
      "Correlation\n",
      "\n",
      "    **7. Correlation**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{correlation} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_g}_{j=1}{p(i,j)ij-\\mu_x\\mu_y}}{\\sigma_x(i)\\sigma_y(j)}\n",
      "\n",
      "    Correlation is a value between 0 (uncorrelated) and 1 (perfectly correlated) showing the\n",
      "    linear dependency of gray level values to their respective voxels in the GLCM.\n",
      "\n",
      "    .. note::\n",
      "      When there is only 1 discrete gray value in the ROI (flat region), :math:`\\sigma_x` and :math:`\\sigma_y` will be\n",
      "      0. In this case, an arbitrary value of 1 is returned instead. This is assessed on a per-angle basis.\n",
      "    \n",
      "Autocorrelation\n",
      "\n",
      "    **1. Autocorrelation**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{autocorrelation} = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_g}_{j=1}{p(i,j)ij}\n",
      "\n",
      "    Autocorrelation is a measure of the magnitude of the fineness and coarseness of texture.\n",
      "    \n",
      "SumEntropy\n",
      "\n",
      "    **23. Sum Entropy**\n",
      "\n",
      "    .. math::\n",
      "\n",
      "      \\textit{sum entropy} = \\displaystyle\\sum^{2N_g}_{k=2}{p_{x+y}(k)\\log_2\\big(p_{x+y}(k)+\\epsilon\\big)}\n",
      "\n",
      "    Sum Entropy is a sum of neighborhood intensity value differences.\n",
      "    \n",
      "MCC\n",
      "\n",
      "    **16. Maximal Correlation Coefficient (MCC)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{MCC} = \\sqrt{\\text{second largest eigenvalue of Q}}\n",
      "\n",
      "      Q(i, j) = \\displaystyle\\sum^{N_g}_{k=0}{\\frac{p(i,k)p(j, k)}{p_x(i)p_y(k)}}\n",
      "\n",
      "    The Maximal Correlation Coefficient is a measure of complexity of the texture and :math:`0 \\leq MCC \\leq 1`.\n",
      "\n",
      "    In case of a flat region, each GLCM matrix has shape (1, 1), resulting in just 1 eigenvalue. In this case, an\n",
      "    arbitrary value of 1 is returned.\n",
      "    \n",
      "SumSquares\n",
      "\n",
      "    **24. Sum of Squares**\n",
      "\n",
      "    .. math::\n",
      "\n",
      "      \\textit{sum squares} = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_g}_{j=1}{(i-\\mu_x)^2p(i,j)}\n",
      "\n",
      "    Sum of Squares or Variance is a measure in the distribution of neighboring intensity level pairs\n",
      "    about the mean intensity level in the GLCM.\n",
      "\n",
      "    .. warning::\n",
      "\n",
      "      This formula represents the variance of the distribution of :math:`i` and is independent from the distribution\n",
      "      of :math:`j`. Therefore, only use this formula if the GLCM is symmetrical, where\n",
      "      :math:`p_x(i) = p_y(j) \\text{, where } i = j`\n",
      "\n",
      "    .. note::\n",
      "      Defined by IBSI as Joint Variance\n",
      "    \n",
      "ClusterProminence\n",
      "\n",
      "    **3. Cluster Prominence**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{cluster prominence} = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_g}_{j=1}\n",
      "      {\\big( i+j-\\mu_x-\\mu_y\\big)^4p(i,j)}\n",
      "\n",
      "    Cluster Prominence is a measure of the skewness and asymmetry of the GLCM. A higher values implies more asymmetry\n",
      "    about the mean while a lower value indicates a peak near the mean value and less variation about the mean.\n",
      "    \n",
      "Imc2\n",
      "\n",
      "    **14. Informational Measure of Correlation (IMC) 2**\n",
      "\n",
      "    .. math::\n",
      "\n",
      "      \\textit{IMC 2} = \\displaystyle\\sqrt{1-e^{-2(HXY2-HXY)}}\n",
      "\n",
      "    IMC2 also assesses the correlation between the probability distributions of :math:`i` and :math:`j` (quantifying the\n",
      "    complexity of the texture). Of interest is to note that :math:`HXY1 = HXY2` and that :math:`HXY2 - HXY \\geq 0`\n",
      "    represents the mutual information of the 2 distributions. Therefore, the range of IMC2 = [0, 1), with 0 representing\n",
      "    the case of 2 independent distributions (no mutual information) and the maximum value representing the case of 2\n",
      "    fully dependent and uniform distributions (maximal mutual information, equal to :math:`\\log_2(N_g)`). In this latter\n",
      "    case, the maximum value is then equal to :math:`\\displaystyle\\sqrt{1-e^{-2\\log_2(N_g)}}`, approaching 1.\n",
      "\n",
      "    .. note::\n",
      "\n",
      "      Due to machine precision errors, it is possible that HXY > HXY2, which would result in returning complex numbers.\n",
      "      In these cases, a value of 0 is returned for IMC2. This is done on a per-angle basis (i.e. prior to any\n",
      "      averaging).\n",
      "    \n",
      "Imc1\n",
      "\n",
      "    **13. Informational Measure of Correlation (IMC) 1**\n",
      "\n",
      "    .. math::\n",
      "\n",
      "      \\textit{IMC 1} = \\displaystyle\\frac{HXY-HXY1}{\\max\\{HX,HY\\}}\n",
      "\n",
      "    IMC1 assesses the correlation between the probability distributions of :math:`i` and :math:`j` (quantifying the\n",
      "    complexity of the texture), using mutual information I(x, y):\n",
      "\n",
      "    .. math::\n",
      "\n",
      "      I(i, j) = \\sum^{N_g}_{i=1}\\sum^{N_g}_{j=1}{p(i,j)\\log_2\\big(\\frac{p(i,j)}{p_x(i)p_y(j)}\\big)}\n",
      "\n",
      "              = \\sum^{N_g}_{i=1}\\sum^{N_g}_{j=1}{p(i,j)\\big(\\log_2 (p(i,j)) - \\log_2 (p_x(i)p_y(j))\\big)}\n",
      "\n",
      "              = \\sum^{N_g}_{i=1}\\sum^{N_g}_{j=1}{p(i,j)\\log_2 \\big(p(i,j)\\big)} -\n",
      "                \\sum^{N_g}_{i=1}\\sum^{N_g}_{j=1}{p(i,j)\\log_2 \\big(p_x(i)p_y(j)\\big)}\n",
      "\n",
      "              = -HXY + HXY1\n",
      "\n",
      "    However, in this formula, the numerator is defined as HXY - HXY1 (i.e. :math:`-I(x, y)`), and is\n",
      "    therefore :math:`\\leq 0`. This reflects how this feature is defined in the original Haralick paper.\n",
      "\n",
      "    In the case where the distributions are independent, there is no mutual information and the result will therefore be\n",
      "    0. In the case of uniform distribution with complete dependence, mutual information will be equal to\n",
      "    :math:`\\log_2(N_g)`.\n",
      "\n",
      "    Finally, :math:`HXY - HXY1` is divided by the maximum of the 2 marginal entropies, where in the latter case of\n",
      "    complete dependence (not necessarily uniform; low complexity) it will result in :math:`IMC1 = -1`, as\n",
      "    :math:`HX = HY = I(i, j)`.\n",
      "\n",
      "    .. note::\n",
      "\n",
      "      In the case where both HX and HY are 0 (as is the case in a flat region), an arbitrary value of 0 is returned to\n",
      "      prevent a division by 0. This is done on a per-angle basis (i.e. prior to any averaging).\n",
      "    \n",
      "DifferenceAverage\n",
      "\n",
      "    **8. Difference Average**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{difference average} = \\displaystyle\\sum^{N_g-1}_{k=0}{kp_{x-y}(k)}\n",
      "\n",
      "    Difference Average measures the relationship between occurrences of pairs\n",
      "    with similar intensity values and occurrences of pairs with differing intensity\n",
      "    values.\n",
      "    \n",
      "Id\n",
      "\n",
      "    **18. Inverse Difference (ID)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{ID} = \\displaystyle\\sum^{N_g-1}_{k=0}{\\frac{p_{x-y}(k)}{1+k}}\n",
      "\n",
      "    ID (a.k.a. Homogeneity 1) is another measure of the local homogeneity of an image.\n",
      "    With more uniform gray levels, the denominator will remain low, resulting in a higher overall value.\n",
      "    \n",
      "ClusterTendency\n",
      "\n",
      "    **5. Cluster Tendency**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{cluster tendency} = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_g}_{j=1}\n",
      "      {\\big(i+j-\\mu_x-\\mu_y\\big)^2p(i,j)}\n",
      "\n",
      "    Cluster Tendency is a measure of groupings of voxels with similar gray-level values.\n",
      "    \n"
     ]
    }
   ],
   "source": [
    "# Print out the docstrings of the enabled features\n",
    "print('Will calculate the following GLCM features: ')\n",
    "for f in glcmFeatures.enabledFeatures:\n",
    "  print(f)\n",
    "  print(getattr(glcmFeatures, f'get{f}FeatureValue').__doc__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "GLCM is symmetrical, therefore Sum Average = 2 * Joint Average, only 1 needs to be calculated\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Calculating GLCM features...\n",
      "done\n",
      "Calculated GLCM features: \n",
      "   JointAverage : 16.55380772442751\n",
      "   SumAverage : 33.10761544885502\n",
      "   JointEntropy : 8.799696270248813\n",
      "   ClusterShade : 19.605083427286676\n",
      "   MaximumProbability : 0.007352392266290182\n",
      "   Idmn : 0.961402169623227\n",
      "   JointEnergy : 0.002893149242988865\n",
      "   Contrast : 47.492125114429776\n",
      "   DifferenceEntropy : 3.74406097806642\n",
      "   InverseVariance : 0.19881884197093194\n",
      "   DifferenceVariance : 16.65563705027098\n",
      "   Idn : 0.8726052157397169\n",
      "   Idm : 0.20022255640475703\n",
      "   Correlation : 0.3917522006696661\n",
      "   Autocorrelation : 289.5436994017259\n",
      "   SumEntropy : 5.354241321485615\n",
      "   MCC : 0.49904046795855606\n",
      "   SumSquares : 39.05587959224222\n",
      "   ClusterProminence : 27995.937591943148\n",
      "   Imc2 : 0.6942249020670357\n",
      "   Imc1 : -0.09438938808738298\n",
      "   DifferenceAverage : 5.284468789866316\n",
      "   Id : 0.28722572382985156\n",
      "   ClusterTendency : 108.73139325453903\n"
     ]
    }
   ],
   "source": [
    "# Calculate the features and print(out result)\n",
    "print('Calculating GLCM features...',)\n",
    "result = glcmFeatures.execute()\n",
    "print('done')\n",
    "\n",
    "print('Calculated GLCM features: ')\n",
    "for (key, val) in result.items():\n",
    "  print('  ', key, ':', val)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Calculate GLRLM Features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "glrlmFeatures = glrlm.RadiomicsGLRLM(croppedImage, croppedMask, **settings)\n",
    "\n",
    "# Set the features to be calculated\n",
    "# glrlmFeatures.enableFeatureByName('ShortRunEmphasis', True)\n",
    "glrlmFeatures.enableAllFeatures()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Will calculate the following GLRLM features: \n",
      "ShortRunLowGrayLevelEmphasis\n",
      "\n",
      "    **13. Short Run Low Gray Level Emphasis (SRLGLE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{SRLGLE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_r}_{j=1}{\\frac{\\textbf{P}(i,j|\\theta)}{i^2j^2}}}{N_r(\\theta)}\n",
      "\n",
      "    SRLGLE measures the joint distribution of shorter run lengths with lower gray-level values.\n",
      "    \n",
      "GrayLevelVariance\n",
      "\n",
      "    **8. Gray Level Variance (GLV)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{GLV} = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_r}_{j=1}{p(i,j|\\theta)(i - \\mu)^2}\n",
      "\n",
      "    Here, :math:`\\mu = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_r}_{j=1}{p(i,j|\\theta)i}`\n",
      "\n",
      "    GLV measures the variance in gray level intensity for the runs.\n",
      "    \n",
      "LowGrayLevelRunEmphasis\n",
      "\n",
      "    **11. Low Gray Level Run Emphasis (LGLRE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{LGLRE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_r}_{j=1}{\\frac{\\textbf{P}(i,j|\\theta)}{i^2}}}{N_r(\\theta)}\n",
      "\n",
      "    LGLRE measures the distribution of low gray-level values, with a higher value indicating a greater concentration of\n",
      "    low gray-level values in the image.\n",
      "    \n",
      "GrayLevelNonUniformityNormalized\n",
      "\n",
      "    **4. Gray Level Non-Uniformity Normalized (GLNN)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{GLNN} = \\frac{\\sum^{N_g}_{i=1}\\left(\\sum^{N_r}_{j=1}{\\textbf{P}(i,j|\\theta)}\\right)^2}{N_r(\\theta)^2}\n",
      "\n",
      "    GLNN measures the similarity of gray-level intensity values in the image, where a lower GLNN value correlates with a\n",
      "    greater similarity in intensity values. This is the normalized version of the GLN formula.\n",
      "    \n",
      "RunVariance\n",
      "\n",
      "    **9. Run Variance (RV)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{RV} = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_r}_{j=1}{p(i,j|\\theta)(j - \\mu)^2}\n",
      "\n",
      "    Here, :math:`\\mu = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_r}_{j=1}{p(i,j|\\theta)j}`\n",
      "\n",
      "    RV is a measure of the variance in runs for the run lengths.\n",
      "    \n",
      "GrayLevelNonUniformity\n",
      "\n",
      "    **3. Gray Level Non-Uniformity (GLN)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{GLN} = \\frac{\\sum^{N_g}_{i=1}\\left(\\sum^{N_r}_{j=1}{\\textbf{P}(i,j|\\theta)}\\right)^2}{N_r(\\theta)}\n",
      "\n",
      "    GLN measures the similarity of gray-level intensity values in the image, where a lower GLN value correlates with a\n",
      "    greater similarity in intensity values.\n",
      "    \n",
      "LongRunEmphasis\n",
      "\n",
      "    **2. Long Run Emphasis (LRE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{LRE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_r}_{j=1}{\\textbf{P}(i,j|\\theta)j^2}}{N_r(\\theta)}\n",
      "\n",
      "    LRE is a measure of the distribution of long run lengths, with a greater value indicative of longer run lengths and\n",
      "    more coarse structural textures.\n",
      "    \n",
      "ShortRunHighGrayLevelEmphasis\n",
      "\n",
      "    **14. Short Run High Gray Level Emphasis (SRHGLE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{SRHGLE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_r}_{j=1}{\\frac{\\textbf{P}(i,j|\\theta)i^2}{j^2}}}{N_r(\\theta)}\n",
      "\n",
      "    SRHGLE measures the joint distribution of shorter run lengths with higher gray-level values.\n",
      "    \n",
      "RunLengthNonUniformity\n",
      "\n",
      "    **5. Run Length Non-Uniformity (RLN)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{RLN} = \\frac{\\sum^{N_r}_{j=1}\\left(\\sum^{N_g}_{i=1}{\\textbf{P}(i,j|\\theta)}\\right)^2}{N_r(\\theta)}\n",
      "\n",
      "    RLN measures the similarity of run lengths throughout the image, with a lower value indicating more homogeneity\n",
      "    among run lengths in the image.\n",
      "    \n",
      "ShortRunEmphasis\n",
      "\n",
      "    **1. Short Run Emphasis (SRE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{SRE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_r}_{j=1}{\\frac{\\textbf{P}(i,j|\\theta)}{j^2}}}{N_r(\\theta)}\n",
      "\n",
      "    SRE is a measure of the distribution of short run lengths, with a greater value indicative of shorter run lengths\n",
      "    and more fine textural textures.\n",
      "    \n",
      "LongRunHighGrayLevelEmphasis\n",
      "\n",
      "    **16. Long Run High Gray Level Emphasis (LRHGLE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{LRHGLRE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_r}_{j=1}{\\textbf{P}(i,j|\\theta)i^2j^2}}{N_r(\\theta)}\n",
      "\n",
      "    LRHGLRE measures the joint distribution of long run lengths with higher gray-level values.\n",
      "    \n",
      "RunPercentage\n",
      "\n",
      "    **7. Run Percentage (RP)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{RP} = {\\frac{N_r(\\theta)}{N_p}}\n",
      "\n",
      "    RP measures the coarseness of the texture by taking the ratio of number of runs and number of voxels in the ROI.\n",
      "\n",
      "    Values are in range :math:`\\frac{1}{N_p} \\leq RP \\leq 1`, with higher values indicating a larger portion of the ROI\n",
      "    consists of short runs (indicates a more fine texture).\n",
      "\n",
      "    .. note::\n",
      "      Note that when weighting is applied and matrices are merged before calculation, :math:`N_p` is multiplied by\n",
      "      :math:`n` number of matrices merged to ensure correct normalization (as each voxel is considered :math:`n` times)\n",
      "    \n",
      "LongRunLowGrayLevelEmphasis\n",
      "\n",
      "    **15. Long Run Low Gray Level Emphasis (LRLGLE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{LRLGLRE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_r}_{j=1}{\\frac{\\textbf{P}(i,j|\\theta)j^2}{i^2}}}{N_r(\\theta)}\n",
      "\n",
      "    LRLGLRE measures the joint distribution of long run lengths with lower gray-level values.\n",
      "    \n",
      "RunEntropy\n",
      "\n",
      "    **10. Run Entropy (RE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{RE} = -\\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_r}_{j=1}\n",
      "      {p(i,j|\\theta)\\log_{2}(p(i,j|\\theta)+\\epsilon)}\n",
      "\n",
      "    Here, :math:`\\epsilon` is an arbitrarily small positive number (:math:`\\approx 2.2\\times10^{-16}`).\n",
      "\n",
      "    RE measures the uncertainty/randomness in the distribution of run lengths and gray levels. A higher value indicates\n",
      "    more heterogeneity in the texture patterns.\n",
      "    \n",
      "HighGrayLevelRunEmphasis\n",
      "\n",
      "    **12. High Gray Level Run Emphasis (HGLRE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{HGLRE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_r}_{j=1}{\\textbf{P}(i,j|\\theta)i^2}}{N_r(\\theta)}\n",
      "\n",
      "    HGLRE measures the distribution of the higher gray-level values, with a higher value indicating a greater\n",
      "    concentration of high gray-level values in the image.\n",
      "    \n",
      "RunLengthNonUniformityNormalized\n",
      "\n",
      "    **6. Run Length Non-Uniformity Normalized (RLNN)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{RLNN} = \\frac{\\sum^{N_r}_{j=1}\\left(\\sum^{N_g}_{i=1}{\\textbf{P}(i,j|\\theta)}\\right)^2}{N_r(\\theta)^2}\n",
      "\n",
      "    RLNN measures the similarity of run lengths throughout the image, with a lower value indicating more homogeneity\n",
      "    among run lengths in the image. This is the normalized version of the RLN formula.\n",
      "    \n"
     ]
    }
   ],
   "source": [
    "# Print out the docstrings of the enabled features\n",
    "print('Will calculate the following GLRLM features: ')\n",
    "for f in glrlmFeatures.enabledFeatures:\n",
    "  print(f)\n",
    "  print(getattr(glrlmFeatures, f'get{f}FeatureValue').__doc__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Calculating GLRLM features...\n",
      "done\n",
      "Calculated GLRLM features: \n",
      "   ShortRunLowGrayLevelEmphasis : 0.008229766244155428\n",
      "   GrayLevelVariance : 39.118151021979244\n",
      "   LowGrayLevelRunEmphasis : 0.008600397891661503\n",
      "   GrayLevelNonUniformityNormalized : 0.04514123814981055\n",
      "   RunVariance : 0.08479457789590625\n",
      "   GrayLevelNonUniformity : 175.6351923150419\n",
      "   LongRunEmphasis : 1.2268440382584342\n",
      "   ShortRunHighGrayLevelEmphasis : 268.9741798411307\n",
      "   RunLengthNonUniformity : 3500.0432315746298\n",
      "   ShortRunEmphasis : 0.9559391731405504\n",
      "   LongRunHighGrayLevelEmphasis : 341.2865790983503\n",
      "   RunPercentage : 0.9404064632491029\n",
      "   LongRunLowGrayLevelEmphasis : 0.010601170478748765\n",
      "   RunEntropy : 4.915038003159503\n",
      "   HighGrayLevelRunEmphasis : 281.066493908972\n",
      "   RunLengthNonUniformityNormalized : 0.8950494659480998\n"
     ]
    }
   ],
   "source": [
    "# Calculate the features and print(out result)\n",
    "print('Calculating GLRLM features...',)\n",
    "result = glrlmFeatures.execute()\n",
    "print('done')\n",
    "\n",
    "print('Calculated GLRLM features: ')\n",
    "for (key, val) in result.items():\n",
    "  print('  ', key, ':', val)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Calculate GLSZM Features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "glszmFeatures = glszm.RadiomicsGLSZM(croppedImage, croppedMask, **settings)\n",
    "\n",
    "# Set the features to be calculated\n",
    "# glszmFeatures.enableFeatureByName('LargeAreaEmphasis', True)\n",
    "glszmFeatures.enableAllFeatures()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Will calculate the following GLSZM features: \n",
      "GrayLevelVariance\n",
      "\n",
      "    **8. Gray Level Variance (GLV)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{GLV} = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_s}_{j=1}{p(i,j)(i - \\mu)^2}\n",
      "\n",
      "    Here, :math:`\\mu = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_s}_{j=1}{p(i,j)i}`\n",
      "\n",
      "    GLV measures the variance in gray level intensities for the zones.\n",
      "    \n",
      "SmallAreaHighGrayLevelEmphasis\n",
      "\n",
      "    **14. Small Area High Gray Level Emphasis (SAHGLE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{SAHGLE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_s}_{j=1}{\\frac{\\textbf{P}(i,j)i^2}{j^2}}}{N_z}\n",
      "\n",
      "    SAHGLE measures the proportion in the image of the joint distribution of smaller size zones with higher gray-level\n",
      "    values.\n",
      "    \n",
      "GrayLevelNonUniformityNormalized\n",
      "\n",
      "    **4. Gray Level Non-Uniformity Normalized (GLNN)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{GLNN} = \\frac{\\sum^{N_g}_{i=1}\\left(\\sum^{N_s}_{j=1}{\\textbf{P}(i,j)}\\right)^2}{N_z^2}\n",
      "\n",
      "    GLNN measures the variability of gray-level intensity values in the image, with a lower value indicating a greater\n",
      "    similarity in intensity values. This is the normalized version of the GLN formula.\n",
      "    \n",
      "SizeZoneNonUniformityNormalized\n",
      "\n",
      "    **6. Size-Zone Non-Uniformity Normalized (SZNN)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{SZNN} = \\frac{\\sum^{N_s}_{j=1}\\left(\\sum^{N_g}_{i=1}{\\textbf{P}(i,j)}\\right)^2}{N_z^2}\n",
      "\n",
      "    SZNN measures the variability of size zone volumes throughout the image, with a lower value indicating more\n",
      "    homogeneity among zone size volumes in the image. This is the normalized version of the SZN formula.\n",
      "    \n",
      "SizeZoneNonUniformity\n",
      "\n",
      "    **5. Size-Zone Non-Uniformity (SZN)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{SZN} = \\frac{\\sum^{N_s}_{j=1}\\left(\\sum^{N_g}_{i=1}{\\textbf{P}(i,j)}\\right)^2}{N_z}\n",
      "\n",
      "    SZN measures the variability of size zone volumes in the image, with a lower value indicating more homogeneity in\n",
      "    size zone volumes.\n",
      "    \n",
      "GrayLevelNonUniformity\n",
      "\n",
      "    **3. Gray Level Non-Uniformity (GLN)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{GLN} = \\frac{\\sum^{N_g}_{i=1}\\left(\\sum^{N_s}_{j=1}{\\textbf{P}(i,j)}\\right)^2}{N_z}\n",
      "\n",
      "    GLN measures the variability of gray-level intensity values in the image, with a lower value indicating more\n",
      "    homogeneity in intensity values.\n",
      "    \n",
      "LargeAreaEmphasis\n",
      "\n",
      "    **2. Large Area Emphasis (LAE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{LAE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_s}_{j=1}{\\textbf{P}(i,j)j^2}}{N_z}\n",
      "\n",
      "    LAE is a measure of the distribution of large area size zones, with a greater value indicative of more larger size\n",
      "    zones and more coarse textures.\n",
      "    \n",
      "ZoneVariance\n",
      "\n",
      "    **9. Zone Variance (ZV)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{ZV} = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_s}_{j=1}{p(i,j)(j - \\mu)^2}\n",
      "\n",
      "    Here, :math:`\\mu = \\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_s}_{j=1}{p(i,j)j}`\n",
      "\n",
      "    ZV measures the variance in zone size volumes for the zones.\n",
      "    \n",
      "ZonePercentage\n",
      "\n",
      "    **7. Zone Percentage (ZP)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{ZP} = \\frac{N_z}{N_p}\n",
      "\n",
      "    ZP measures the coarseness of the texture by taking the ratio of number of zones and number of voxels in the ROI.\n",
      "\n",
      "    Values are in range :math:`\\frac{1}{N_p} \\leq ZP \\leq 1`, with higher values indicating a larger portion of the ROI\n",
      "    consists of small zones (indicates a more fine texture).\n",
      "    \n",
      "LargeAreaLowGrayLevelEmphasis\n",
      "\n",
      "    **15. Large Area Low Gray Level Emphasis (LALGLE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{LALGLE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_s}_{j=1}{\\frac{\\textbf{P}(i,j)j^2}{i^2}}}{N_z}\n",
      "\n",
      "    LALGLE measures the proportion in the image of the joint distribution of larger size zones with lower gray-level\n",
      "    values.\n",
      "    \n",
      "LargeAreaHighGrayLevelEmphasis\n",
      "\n",
      "    **16. Large Area High Gray Level Emphasis (LAHGLE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{LAHGLE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_s}_{j=1}{\\textbf{P}(i,j)i^2j^2}}{N_z}\n",
      "\n",
      "    LAHGLE measures the proportion in the image of the joint distribution of larger size zones with higher gray-level\n",
      "    values.\n",
      "    \n",
      "HighGrayLevelZoneEmphasis\n",
      "\n",
      "    **12. High Gray Level Zone Emphasis (HGLZE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{HGLZE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_s}_{j=1}{\\textbf{P}(i,j)i^2}}{N_z}\n",
      "\n",
      "    HGLZE measures the distribution of the higher gray-level values, with a higher value indicating a greater proportion\n",
      "    of higher gray-level values and size zones in the image.\n",
      "    \n",
      "SmallAreaEmphasis\n",
      "\n",
      "    **1. Small Area Emphasis (SAE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{SAE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_s}_{j=1}{\\frac{\\textbf{P}(i,j)}{j^2}}}{N_z}\n",
      "\n",
      "    SAE is a measure of the distribution of small size zones, with a greater value indicative of more smaller size zones\n",
      "    and more fine textures.\n",
      "    \n",
      "LowGrayLevelZoneEmphasis\n",
      "\n",
      "    **11. Low Gray Level Zone Emphasis (LGLZE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{LGLZE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_s}_{j=1}{\\frac{\\textbf{P}(i,j)}{i^2}}}{N_z}\n",
      "\n",
      "    LGLZE measures the distribution of lower gray-level size zones, with a higher value indicating a greater proportion\n",
      "    of lower gray-level values and size zones in the image.\n",
      "    \n",
      "ZoneEntropy\n",
      "\n",
      "    **10. Zone Entropy (ZE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{ZE} = -\\displaystyle\\sum^{N_g}_{i=1}\\displaystyle\\sum^{N_s}_{j=1}{p(i,j)\\log_{2}(p(i,j)+\\epsilon)}\n",
      "\n",
      "    Here, :math:`\\epsilon` is an arbitrarily small positive number (:math:`\\approx 2.2\\times10^{-16}`).\n",
      "\n",
      "    ZE measures the uncertainty/randomness in the distribution of zone sizes and gray levels. A higher value indicates\n",
      "    more heterogeneneity in the texture patterns.\n",
      "    \n",
      "SmallAreaLowGrayLevelEmphasis\n",
      "\n",
      "    **13. Small Area Low Gray Level Emphasis (SALGLE)**\n",
      "\n",
      "    .. math::\n",
      "      \\textit{SALGLE} = \\frac{\\sum^{N_g}_{i=1}\\sum^{N_s}_{j=1}{\\frac{\\textbf{P}(i,j)}{i^2j^2}}}{N_z}\n",
      "\n",
      "    SALGLE measures the proportion in the image of the joint distribution of smaller size zones with lower gray-level\n",
      "    values.\n",
      "    \n"
     ]
    }
   ],
   "source": [
    "# Print out the docstrings of the enabled features\n",
    "print('Will calculate the following GLSZM features: ')\n",
    "for f in glszmFeatures.enabledFeatures:\n",
    "  print(f)\n",
    "  print(getattr(glszmFeatures, f'get{f}FeatureValue').__doc__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Calculating GLSZM features...\n",
      "done\n",
      "Calculated GLSZM features: \n",
      "   GrayLevelVariance : 40.60313992393263\n",
      "   ZoneVariance : 8.721239097486347\n",
      "   GrayLevelNonUniformityNormalized : 0.044057307901283996\n",
      "   SizeZoneNonUniformityNormalized : 0.3997843804512568\n",
      "   SizeZoneNonUniformity : 747.5967914438503\n",
      "   GrayLevelNonUniformity : 82.38716577540107\n",
      "   LargeAreaEmphasis : 13.615508021390374\n",
      "   SmallAreaHighGrayLevelEmphasis : 193.438051925864\n",
      "   ZonePercentage : 0.4520183708000967\n",
      "   LargeAreaLowGrayLevelEmphasis : 0.12723841553344326\n",
      "   LargeAreaHighGrayLevelEmphasis : 3514.7614973262034\n",
      "   HighGrayLevelZoneEmphasis : 288.6235294117647\n",
      "   SmallAreaEmphasis : 0.6564478999587141\n",
      "   LowGrayLevelZoneEmphasis : 0.009100942027706215\n",
      "   ZoneEntropy : 6.50821498619819\n",
      "   SmallAreaLowGrayLevelEmphasis : 0.006416982055097711\n"
     ]
    }
   ],
   "source": [
    "# Calculate the features and print(out result)\n",
    "print('Calculating GLSZM features...',)\n",
    "result = glszmFeatures.execute()\n",
    "print('done')\n",
    "\n",
    "print('Calculated GLSZM features: ')\n",
    "for (key, val) in result.items():\n",
    "  print('  ', key, ':', val)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Calculate Features using Laplacian of Gaussian Filter"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Calculating features on filtered images is very similar to calculating features on the original image. All filters in PyRadiomics have the same input and output signature, and there is even one for applying no filter. This enables to loop over a list of requested filters and apply them in the same piece of code. It is applied like this in the execute function in feature extractor. The input for the filters is the image, with additional keywords. If no additional keywords are supplied, the filter uses default values where applicable. It returns a [generator object](https://docs.python.org/2/reference/simple_stmts.html?#yield), allowing to define the generators to be applied before the filters functions are actually called."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Calculate Firstorder on LoG filtered images"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "logFeatures = {}\n",
    "sigmaValues = [1.0, 3.0, 5.0]\n",
    "for orig_LogImage, imageTypename, inputSettings in imageoperations.getLoGImage(image, mask, sigma=sigmaValues):\n",
    "  logImage, croppedMask = imageoperations.cropToTumorMask(orig_LogImage, mask, bb)\n",
    "  logFirstorderFeatures = firstorder.RadiomicsFirstOrder(logImage, croppedMask, **inputSettings)\n",
    "  logFirstorderFeatures.enableAllFeatures()\n",
    "  logFeatures[imageTypename] = logFirstorderFeatures.execute()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   log-sigma-3-0-mm-3D_InterquartileRange : 103.15813827514648\n",
      "   log-sigma-3-0-mm-3D_Skewness : -0.49838634399478493\n",
      "   log-sigma-3-0-mm-3D_Uniformity : 0.09064784923477494\n",
      "   log-sigma-3-0-mm-3D_Median : -73.3129653930664\n",
      "   log-sigma-3-0-mm-3D_Energy : 56119386.49315185\n",
      "   log-sigma-3-0-mm-3D_RobustMeanAbsoluteDeviation : 43.37792439842861\n",
      "   log-sigma-3-0-mm-3D_MeanAbsoluteDeviation : 64.33120246325181\n",
      "   log-sigma-3-0-mm-3D_TotalEnergy : 222641609.01213792\n",
      "   log-sigma-3-0-mm-3D_Maximum : 114.29669189453125\n",
      "   log-sigma-3-0-mm-3D_RootMeanSquared : 116.46989846118638\n",
      "   log-sigma-3-0-mm-3D_90Percentile : 13.917341041564946\n",
      "   log-sigma-3-0-mm-3D_Minimum : -354.3352355957031\n",
      "   log-sigma-3-0-mm-3D_Entropy : 3.72121444058449\n",
      "   log-sigma-3-0-mm-3D_Range : 468.6319274902344\n",
      "   log-sigma-3-0-mm-3D_Variance : 6720.0665187057575\n",
      "   log-sigma-3-0-mm-3D_10Percentile : -197.0173400878906\n",
      "   log-sigma-3-0-mm-3D_Kurtosis : 3.1833658319698688\n",
      "   log-sigma-3-0-mm-3D_Mean : -82.73554694841455\n",
      "   log-sigma-1-0-mm-3D_InterquartileRange : 81.87671852111816\n",
      "   log-sigma-1-0-mm-3D_Skewness : -0.22090525170411396\n",
      "   log-sigma-1-0-mm-3D_Uniformity : 0.11423531337174343\n",
      "   log-sigma-1-0-mm-3D_Median : -18.91979217529297\n",
      "   log-sigma-1-0-mm-3D_Energy : 18272859.744011104\n",
      "   log-sigma-1-0-mm-3D_RobustMeanAbsoluteDeviation : 34.30945152372748\n",
      "   log-sigma-1-0-mm-3D_MeanAbsoluteDeviation : 49.664661651136576\n",
      "   log-sigma-1-0-mm-3D_TotalEnergy : 72493645.22465338\n",
      "   log-sigma-1-0-mm-3D_Maximum : 164.7267608642578\n",
      "   log-sigma-1-0-mm-3D_RootMeanSquared : 66.46002494100189\n",
      "   log-sigma-1-0-mm-3D_90Percentile : 54.79034423828125\n",
      "   log-sigma-1-0-mm-3D_Minimum : -255.25962829589844\n",
      "   log-sigma-1-0-mm-3D_Entropy : 3.3700495507795636\n",
      "   log-sigma-1-0-mm-3D_Range : 419.98638916015625\n",
      "   log-sigma-1-0-mm-3D_Variance : 3930.907589131821\n",
      "   log-sigma-1-0-mm-3D_10Percentile : -104.93405303955078\n",
      "   log-sigma-1-0-mm-3D_Kurtosis : 3.0718243807249306\n",
      "   log-sigma-1-0-mm-3D_Mean : -22.046027443210075\n",
      "   log-sigma-5-0-mm-3D_InterquartileRange : 106.34271621704102\n",
      "   log-sigma-5-0-mm-3D_Skewness : -0.30549686903008444\n",
      "   log-sigma-5-0-mm-3D_Uniformity : 0.09026759286087939\n",
      "   log-sigma-5-0-mm-3D_Median : -99.11744689941406\n",
      "   log-sigma-5-0-mm-3D_Energy : 72664939.72523072\n",
      "   log-sigma-5-0-mm-3D_RobustMeanAbsoluteDeviation : 43.25629577830131\n",
      "   log-sigma-5-0-mm-3D_MeanAbsoluteDeviation : 63.43642644575672\n",
      "   log-sigma-5-0-mm-3D_TotalEnergy : 288282536.7517086\n",
      "   log-sigma-5-0-mm-3D_Maximum : 117.41451263427734\n",
      "   log-sigma-5-0-mm-3D_RootMeanSquared : 132.5316785234327\n",
      "   log-sigma-5-0-mm-3D_90Percentile : -10.697756195068333\n",
      "   log-sigma-5-0-mm-3D_Minimum : -347.3450012207031\n",
      "   log-sigma-5-0-mm-3D_Entropy : 3.713363914131388\n",
      "   log-sigma-5-0-mm-3D_Range : 464.75951385498047\n",
      "   log-sigma-5-0-mm-3D_Variance : 6483.793919012423\n",
      "   log-sigma-5-0-mm-3D_10Percentile : -211.97431640625\n",
      "   log-sigma-5-0-mm-3D_Kurtosis : 3.114891608730306\n",
      "   log-sigma-5-0-mm-3D_Mean : -105.26562541127133\n"
     ]
    }
   ],
   "source": [
    "# Show result\n",
    "for sigma, features in logFeatures.items():\n",
    "  for (key, val) in features.items():\n",
    "    laplacianFeatureName = f'{sigma!s}_{key}'\n",
    "    print('  ', laplacianFeatureName, ':', val)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Calculate Features using Wavelet filter"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Calculate Firstorder on filtered images"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Calculate firstorder features with  wavelet-HLL\n",
      "Calculate firstorder features with  wavelet-LHL\n",
      "Calculate firstorder features with  wavelet-LHH\n",
      "Calculate firstorder features with  wavelet-LLH\n",
      "Calculate firstorder features with  wavelet-HLH\n",
      "Calculate firstorder features with  wavelet-HHH\n",
      "Calculate firstorder features with  wavelet-HHL\n",
      "Calculate firstorder features with  wavelet-LLL\n"
     ]
    }
   ],
   "source": [
    "waveletFeatures = {}\n",
    "for orig_decompositionImage, decompositionName, inputSettings in imageoperations.getWaveletImage(image, mask):\n",
    "  decompositionImage, croppedMask = imageoperations.cropToTumorMask(orig_decompositionImage, mask, bb)\n",
    "  waveletFirstOrderFeaturs = firstorder.RadiomicsFirstOrder(decompositionImage, croppedMask, **inputSettings)\n",
    "  waveletFirstOrderFeaturs.enableAllFeatures()\n",
    "\n",
    "  print('Calculate firstorder features with ', decompositionName)\n",
    "  waveletFeatures[decompositionName] = waveletFirstOrderFeaturs.execute()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   wavelet-LLL_InterquartileRange : 550.5942674265389\n",
      "   wavelet-LLL_Skewness : 0.22884642646488648\n",
      "   wavelet-LLL_Uniformity : 0.019907776727807427\n",
      "   wavelet-LLL_Median : 2244.886736086164\n",
      "   wavelet-LLL_Energy : 21547005906.071228\n",
      "   wavelet-LLL_RobustMeanAbsoluteDeviation : 220.73969717214538\n",
      "   wavelet-LLL_MeanAbsoluteDeviation : 293.1439959437339\n",
      "   wavelet-LLL_TotalEnergy : 85483116692.78741\n",
      "   wavelet-LLL_Maximum : 3180.639186772004\n",
      "   wavelet-LLL_RootMeanSquared : 2282.184255507612\n",
      "   wavelet-LLL_90Percentile : 2739.69052111044\n",
      "   wavelet-LLL_Minimum : 1468.0772410291193\n",
      "   wavelet-LLL_Entropy : 5.783004890516309\n",
      "   wavelet-LLL_Range : 1712.5619457428847\n",
      "   wavelet-LLL_Variance : 122620.56279600722\n",
      "   wavelet-LLL_10Percentile : 1812.6847348869353\n",
      "   wavelet-LLL_Kurtosis : 2.2736564306682845\n",
      "   wavelet-LLL_Mean : 2255.1595095005646\n",
      "   wavelet-HHH_InterquartileRange : 20.31927464217497\n",
      "   wavelet-HHH_Skewness : -0.06881127372370828\n",
      "   wavelet-HHH_Uniformity : 0.38291997981392567\n",
      "   wavelet-HHH_Median : 0.10911729278904754\n",
      "   wavelet-HHH_Energy : 1241014.7870147303\n",
      "   wavelet-HHH_RobustMeanAbsoluteDeviation : 8.5302745069224\n",
      "   wavelet-HHH_MeanAbsoluteDeviation : 13.075975686184734\n",
      "   wavelet-HHH_TotalEnergy : 4923459.543210291\n",
      "   wavelet-HHH_Maximum : 76.40996501874992\n",
      "   wavelet-HHH_RootMeanSquared : 17.319913459004184\n",
      "   wavelet-HHH_90Percentile : 20.923843334408843\n",
      "   wavelet-HHH_Minimum : -74.75569866887916\n",
      "   wavelet-HHH_Entropy : 1.6278116747544993\n",
      "   wavelet-HHH_Range : 151.1656636876291\n",
      "   wavelet-HHH_Variance : 299.95221801349567\n",
      "   wavelet-HHH_10Percentile : -21.03831302561452\n",
      "   wavelet-HHH_Kurtosis : 4.324555498144832\n",
      "   wavelet-HHH_Mean : 0.1648763594289033\n",
      "   wavelet-LLH_InterquartileRange : 352.67245821032066\n",
      "   wavelet-LLH_Skewness : -0.5257738152870547\n",
      "   wavelet-LLH_Uniformity : 0.030439966791254963\n",
      "   wavelet-LLH_Median : 62.7368130338552\n",
      "   wavelet-LLH_Energy : 263973676.50526202\n",
      "   wavelet-LLH_RobustMeanAbsoluteDeviation : 146.79059076010634\n",
      "   wavelet-LLH_MeanAbsoluteDeviation : 205.42276939216512\n",
      "   wavelet-LLH_TotalEnergy : 1047258848.4400647\n",
      "   wavelet-LLH_Maximum : 733.8505082763058\n",
      "   wavelet-LLH_RootMeanSquared : 252.60244513407108\n",
      "   wavelet-LLH_90Percentile : 297.9116104034167\n",
      "   wavelet-LLH_Minimum : -783.0088926440542\n",
      "   wavelet-LLH_Entropy : 5.278889240243901\n",
      "   wavelet-LLH_Range : 1516.85940092036\n",
      "   wavelet-LLH_Variance : 63709.17000171525\n",
      "   wavelet-LLH_10Percentile : -370.14521874186516\n",
      "   wavelet-LLH_Kurtosis : 2.6967489992126996\n",
      "   wavelet-LLH_Mean : 9.941090785026738\n",
      "   wavelet-HHL_InterquartileRange : 22.380593815902103\n",
      "   wavelet-HHL_Skewness : 0.12189025030374873\n",
      "   wavelet-HHL_Uniformity : 0.35870148174363325\n",
      "   wavelet-HHL_Median : 0.08293864416523505\n",
      "   wavelet-HHL_Energy : 1537525.5233746145\n",
      "   wavelet-HHL_RobustMeanAbsoluteDeviation : 9.300989159319672\n",
      "   wavelet-HHL_MeanAbsoluteDeviation : 14.408696180462384\n",
      "   wavelet-HHL_TotalEnergy : 6099802.186239617\n",
      "   wavelet-HHL_Maximum : 96.92755982135392\n",
      "   wavelet-HHL_RootMeanSquared : 19.278285450581333\n",
      "   wavelet-HHL_90Percentile : 23.036122247740195\n",
      "   wavelet-HHL_Minimum : -100.72323160995246\n",
      "   wavelet-HHL_Entropy : 1.7542276049711516\n",
      "   wavelet-HHL_Range : 197.6507914313064\n",
      "   wavelet-HHL_Variance : 371.536288126144\n",
      "   wavelet-HHL_10Percentile : -22.006202043327146\n",
      "   wavelet-HHL_Kurtosis : 4.713021547716666\n",
      "   wavelet-HHL_Mean : 0.3405903521121076\n",
      "   wavelet-HLL_InterquartileRange : 53.672122004380526\n",
      "   wavelet-HLL_Skewness : -0.5141660448024011\n",
      "   wavelet-HLL_Uniformity : 0.16358742557378367\n",
      "   wavelet-HLL_Median : -2.8172003576358726\n",
      "   wavelet-HLL_Energy : 9738068.52047006\n",
      "   wavelet-HLL_RobustMeanAbsoluteDeviation : 22.749753908060928\n",
      "   wavelet-HLL_MeanAbsoluteDeviation : 35.75394215262929\n",
      "   wavelet-HLL_TotalEnergy : 38633694.69180624\n",
      "   wavelet-HLL_Maximum : 186.24612312778368\n",
      "   wavelet-HLL_RootMeanSquared : 48.51696801898685\n",
      "   wavelet-HLL_90Percentile : 50.858801790987414\n",
      "   wavelet-HLL_Minimum : -291.543962260902\n",
      "   wavelet-HLL_Entropy : 2.9557322085734774\n",
      "   wavelet-HLL_Range : 477.79008538868567\n",
      "   wavelet-HLL_Variance : 2328.1166596593844\n",
      "   wavelet-HLL_10Percentile : -62.825323624959886\n",
      "   wavelet-HLL_Kurtosis : 5.0993261305473405\n",
      "   wavelet-HLL_Mean : -5.077354241729555\n",
      "   wavelet-HLH_InterquartileRange : 44.116682262690155\n",
      "   wavelet-HLH_Skewness : -0.10963421584646277\n",
      "   wavelet-HLH_Uniformity : 0.19296918351629522\n",
      "   wavelet-HLH_Median : -0.7888938095239306\n",
      "   wavelet-HLH_Energy : 7500010.616793914\n",
      "   wavelet-HLH_RobustMeanAbsoluteDeviation : 18.832879840663065\n",
      "   wavelet-HLH_MeanAbsoluteDeviation : 30.641998266064906\n",
      "   wavelet-HLH_TotalEnergy : 29754680.79172388\n",
      "   wavelet-HLH_Maximum : 195.25285126676468\n",
      "   wavelet-HLH_RootMeanSquared : 42.57828637440775\n",
      "   wavelet-HLH_90Percentile : 48.83999610405644\n",
      "   wavelet-HLH_Minimum : -254.0726963338062\n",
      "   wavelet-HLH_Entropy : 2.7550183352722333\n",
      "   wavelet-HLH_Range : 449.32554760057087\n",
      "   wavelet-HLH_Variance : 1812.8975907682616\n",
      "   wavelet-HLH_10Percentile : -48.79736522405574\n",
      "   wavelet-HLH_Kurtosis : 5.962640061054699\n",
      "   wavelet-HLH_Mean : -0.1134892629941303\n",
      "   wavelet-LHL_InterquartileRange : 71.49977707015142\n",
      "   wavelet-LHL_Skewness : -0.3695385954220589\n",
      "   wavelet-LHL_Uniformity : 0.12136669796711834\n",
      "   wavelet-LHL_Median : -4.097211683834559\n",
      "   wavelet-LHL_Energy : 18447257.204823643\n",
      "   wavelet-LHL_RobustMeanAbsoluteDeviation : 30.645212155320817\n",
      "   wavelet-LHL_MeanAbsoluteDeviation : 48.96288225290898\n",
      "   wavelet-LHL_TotalEnergy : 73185529.68222265\n",
      "   wavelet-LHL_Maximum : 286.5712199871117\n",
      "   wavelet-LHL_RootMeanSquared : 66.77642138647703\n",
      "   wavelet-LHL_90Percentile : 71.57965322911353\n",
      "   wavelet-LHL_Minimum : -354.8947330376593\n",
      "   wavelet-LHL_Entropy : 3.404077391894062\n",
      "   wavelet-LHL_Range : 641.465953024771\n",
      "   wavelet-LHL_Variance : 4432.098160235003\n",
      "   wavelet-LHL_10Percentile : -85.64089631106806\n",
      "   wavelet-LHL_Kurtosis : 4.820466352606455\n",
      "   wavelet-LHL_Mean : -5.195410758481324\n",
      "   wavelet-LHH_InterquartileRange : 61.71745143230112\n",
      "   wavelet-LHH_Skewness : 0.19738213136266408\n",
      "   wavelet-LHH_Uniformity : 0.1408097883179142\n",
      "   wavelet-LHH_Median : -1.9400920999742608\n",
      "   wavelet-LHH_Energy : 13202719.569231834\n",
      "   wavelet-LHH_RobustMeanAbsoluteDeviation : 26.47232854294366\n",
      "   wavelet-LHH_MeanAbsoluteDeviation : 41.63688459313146\n",
      "   wavelet-LHH_TotalEnergy : 52378953.36914481\n",
      "   wavelet-LHH_Maximum : 279.35038075641216\n",
      "   wavelet-LHH_RootMeanSquared : 56.49225866143942\n",
      "   wavelet-LHH_90Percentile : 63.21517068267353\n",
      "   wavelet-LHH_Minimum : -324.7034536822992\n",
      "   wavelet-LHH_Entropy : 3.1791866447134405\n",
      "   wavelet-LHH_Range : 604.0538344387114\n",
      "   wavelet-LHH_Variance : 3189.2471471516797\n",
      "   wavelet-LHH_10Percentile : -69.12526990814825\n",
      "   wavelet-LHH_Kurtosis : 5.104386781839099\n",
      "   wavelet-LHH_Mean : -1.458815107989458\n"
     ]
    }
   ],
   "source": [
    "# Show result\n",
    "for decompositionName, features in waveletFeatures.items():\n",
    "  for (key, val) in features.items():\n",
    "    waveletFeatureName = f'{decompositionName!s}_{key}'\n",
    "    print('  ', waveletFeatureName, ':', val)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
